package com.xjy.rpc.config;

import com.xjy.rpc.annotation.RpcServer;
import com.xjy.rpc.annotation.ServerRegister;
import com.xjy.rpc.bean.BeanDefinition;
import com.xjy.rpc.bean.ServiceCount;
import com.xjy.rpc.netty.ThreadPool;
import com.xjy.rpc.netty.server.ServerTest;
import com.xjy.rpc.register.IRegisterService;
import com.xjy.rpc.register.RpcRegisterFactory;
import com.xjy.rpc.utils.PropertiesUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

import java.io.File;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @description: TODO 通过注解在redis中注册标记的接口信息,启动服务，缓存socket channel
 * @author XJY
 * @date 2024/9/29 16:01
 * @version 1.0
 */
@Configuration
@Slf4j
public class ServiceProvideConfig implements BeanPostProcessor, EnvironmentAware , InitializingBean {

    String ip;

    {
        try {
            ip = InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
            ip = "127.0.0.1";
        }
    }

    RpcProperties rpcProperties;


    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        //根据注解注册类
        Class<?> aClass = bean.getClass();
        IRegisterService registerService = RpcRegisterFactory.getBean("redis");
        if (aClass.isAnnotationPresent(ServerRegister.class)){
            Method[] methods = aClass.getDeclaredMethods();
            //Method[] methods = aClass.getMethods();
            if (methods != null && methods.length > 0){
                //TODO 先删除再注册
                //registerService.unRegister(rpcProperties.getServiceName());
                for (Method method : methods) {
                    if ("main".equals(method.getName())) continue;
                    //组装bean
                    BeanDefinition definition = getBeanDefinition(method);
                    //方法是否被注解修饰，自定义该服务时间
                    if (method.isAnnotationPresent(RpcServer.class)){
                        final RpcServer rpcServer = method.getAnnotation(RpcServer.class);
                        int i = rpcServer.expireTime();
                        TimeUnit unit = rpcServer.timeUnit();
                        Map<String,Object> config = new HashMap<>();
                        config.put(Constant.EXPIRE_TIME,i);
                        config.put(Constant.TIME_UNIT,unit);
                        registerService.register(definition,config);
                        continue;
                    }
                    //redis注册
                    registerService.register(definition);
                    //本地也来一份
                    //ApiCache.apiMap.put(rpcProperties.getServiceName()+method.getName(),definition);
                }
                log.info("{}服务注册成功",rpcProperties.getServiceName());
            }
        }
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
    //记录服务有个多少个，适用于多服务注册区分
    static final Map<String, ServiceCount> serviceCount = new ConcurrentHashMap<>();

    private BeanDefinition getBeanDefinition(Method method) {
        BeanDefinition definition = new BeanDefinition();
        definition.setId(new Random().nextLong());
        definition.setClassName(method.getDeclaringClass().getName());
        definition.setMethodName(method.getName());
        definition.setModifiers(method.getModifiers());
        definition.setServiceName(rpcProperties.getServiceName());
        definition.setParametersType(method.getParameterTypes());
        definition.setReturnType(method.getReturnType());
        definition.setIp(ip);
        definition.setPort(rpcProperties.getPort());
        definition.setServiceCount(0);
        return definition;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        //启动netty服务  后续消费者调用接口走这个服务解析
        Thread t = null;
        try {
            t = new Thread(() -> {
                new ServerTest(ip, rpcProperties.getPort()).run();
            });
        } catch (Exception e) {
            log.error("netty server start fail {}:{}",ip,rpcProperties.getPort());
            throw new RuntimeException(e);
        }
        t.setDaemon(true);
        ThreadPool.getThreadPool().execute(t);
    }

    @Override
    public void setEnvironment(Environment environment) {
        RpcProperties properties = RpcProperties.getInstance();
        PropertiesUtils.init(properties,environment);
        rpcProperties = properties;
        log.info("读取配置文件成功");
    }
}
